using System.Linq;
using GameFramework;
using UnityGameFramework.Runtime;
using LS.DataTable;
using LS.GameKit;
using LS.UI;

namespace LS.Procedure
{
    /// <summary>
    /// 游戏流程基类
    /// </summary>
    public abstract partial class GameProcedureBase : ProcedureBase
    {
        protected SceneLoader SceneLoader { get; private set; }

        public void LoadScenes(int[] sceneIds, int? bgm = null, bool unloadCurrentScenes = true)
        {
            if (SceneLoader != null)
            {
                Log.Warning("Scenes is already loading!");
                return;
            }

            var dataTableCom = LSEntry.DataTable;
            var lsBaseCom = LSEntry.LSBase;
            
            var dtScene = dataTableCom.GetDataTable(lsBaseCom.m_DataTableDefaultSetting.SceneDataType);
            var sceneNames = 
                sceneIds
                .Select(id => dtScene.GetDataRowObject(id) as ISceneData)
                .Select(sd=>sd.AssetName)
                .ToArray();
            LoadScenes(sceneNames, bgm, unloadCurrentScenes);
        }
        
        public void LoadScenes(string[] sceneNames, int? bgm = null, bool unloadCurrentScenes = true)
        {
            if (SceneLoader != null)
            {
                Log.Warning("Scenes is already loading!");
                return;
            }
            
            var soundCom = LSEntry.Sound;
            var entityCom = LSEntry.Entity;
            var baseCom = LSEntry.Base;
            
            soundCom.StopAllLoadingSounds();
            soundCom.StopAllLoadedSounds();
            
            entityCom.HideAllLoadingEntities();
            entityCom.HideAllLoadedEntities();
            
            baseCom.ResetNormalGameSpeed();
            
            if (bgm.HasValue)
            {
                //播放加载界面背景音乐
                soundCom.PlayMusic(bgm.Value);
            }

            SceneLoader = ReferencePool.Acquire<SceneLoader>();
            SceneLoader.SceneAssetNames = sceneNames;
            SceneLoader.UnloadCurrentScenes = unloadCurrentScenes;
            SceneLoader.BeforeLoadingEvent += BeforeLoad;
            SceneLoader.AfterLoadingEvent += AfterLoad;
            SceneLoader.LoadFinishEvent += LoadFinish;
            SceneLoader.UpdateProgressEvent += UpdateProgress;
            SceneLoader.Start();
        }

        public void UnloadCurrentScenes()
        {
            var sceneCom = LSEntry.Scene;
            CallSceneReferenceLeave();
            string[] loadedSceneAssetNames = sceneCom.GetLoadedSceneAssetNames();
            for (int i = 0; i < loadedSceneAssetNames.Length; i++)
            {
                if (sceneCom.SceneIsUnloading(loadedSceneAssetNames[i]))
                {
                    LSEntry.Scene.UnloadScene(loadedSceneAssetNames[i]);
                }
            }
        }
        
        public virtual void BeforeLoad(SceneLoader loader)
        {
            
        }

        public virtual void AfterLoad(SceneLoader loader)
        {
            
        }

        public virtual void LoadFinish(SceneLoader loader)
        {
            Log.Debug("Load scene finished!");
            var sceneLoader = SceneLoader;
            SceneLoader = null;
            ReferencePool.Release(sceneLoader);
            CallSceneReferenceEnter();
        }

        public virtual void UpdateProgress(SceneLoader loader)
        {
            
        }
    }
}
